package com.huiquan.vocab.service;

import com.huiquan.analysis.domain.User;
import com.huiquan.foundation.constant.RoleID;
import com.huiquan.foundation.constant.SubmitStatus;
import com.huiquan.foundation.service.UserRecordService;
import com.huiquan.foundation.util.BusinessUtil;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.constant.BaseContants;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.management.domain.UserAbility;
import com.huiquan.management.service.UserAbilityService;
import com.huiquan.synonymy.dao.SynonymyWordDao;
import com.huiquan.vocab.constant.VocabConstant;
import com.huiquan.vocab.dao.*;
import com.huiquan.vocab.domain.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Service
public class VocabDyadService extends BaseService {

	@Autowired
	private VocabDyadStdDao vocabDyadStdDao;
	@Autowired
	private VocabDyadDao vocabDyadDao;
	@Autowired
	private VocabDyadRemoveDao vocabDyadRemoveDao;
	@Autowired
	private VocabDyadInitDao vocabDyadInitDao;
	@Autowired
	private VocabDyadInitService vocabDyadInitService;
	@Autowired
	private VocabElementDao vocabElementDao;
	@Autowired
	private UserAbilityService userAbilityService;
	@Autowired
	private UserRecordService userRecordService;
	@Autowired
	private VocabDyadPositionService vocabDyadPositionService;
	/**
	 * O+S条件查询拼接查询SQL
	 * 
	 * @param oAndArr
	 * @param sAndArr
	 * @param oOrArr
	 * @param sOrArr
	 * @param arr
	 * @return
	 */
	private String getSqlForOSSearch(List<String> oAndArr, List<String> sAndArr, List<String> oOrArr,
			List<String> sOrArr, List<String> arr) {
		StringBuffer sql = new StringBuffer();
		int count = 0;
		// 存在小词o and的词
		for (int i = 0; i < oAndArr.size(); i++) {
			sql.append("JOIN bas_vocab_dyad_search m" + count + " ON d.id = m" + count + ".id and ");
			if (arr.size() > 0) {
				sql.append(" ( ");
			}
			// 如果存在只存在or的s小词
			if (sAndArr.size() == 0 && sOrArr.size() > 0 && i == 0) {
				sql.append(" ( ");
			}
			sql.append("( ( m" + count + ".property = 'o' or m" + count + ".property = 'oa') and (m" + count
					+ ".element like '" + oAndArr.get(i) + "' ");
			if (i == 0) {
				for (int j = 0; j < oOrArr.size(); j++) {
					sql.append(" or m" + count + ".element like '" + oOrArr.get(j) + "' ");
				}
				sql.append(" ) ) ");
			} else {
				sql.append(" ) ) ");
			}
			// 如果存在只存在or的s小词 拼接在第一个join
			if (sAndArr.size() == 0 && sOrArr.size() > 0 && i == 0) {
				sql.append(" or (  (m" + count + ".property = 's' or m" + count + ".property = 'si')  and ( ");
				for (int j = 0; j < sOrArr.size(); j++) {
					if (j == 0) {
						sql.append(" m" + count + ".element like '" + sOrArr.get(j) + "' ");
					} else {
						sql.append(" or m" + count + ".element like '" + sOrArr.get(j) + "' ");
					}
				}
				sql.append(" ) ) ) ");
			}
			// 拼接含有%的词
			if (arr.size() > 0) {
				for (int k = 0; k < arr.size(); k++) {
					sql.append(" or d.array LIKE '" + arr.get(k) + "' ");
				}
				sql.append(" ) ");
			}
			count++;
		}
		// s and列表
		for (int i = 0; i < sAndArr.size(); i++) {
			sql.append("JOIN bas_vocab_dyad_search m" + count + " ON d.id = m" + count + ".id and ");
			if (arr.size() > 0) {
				sql.append(" ( ");
			}
			sql.append("( ( m" + count + ".property = 's' or m" + count + ".property = 'si' ) and (m" + count
					+ ".element like '" + sAndArr.get(i) + "' ");
			if (i == 0) {
				for (int j = 0; j < sOrArr.size(); j++) {
					sql.append(" or m" + count + ".element like '" + sOrArr.get(j) + "' ");
				}
				sql.append(" ) ) ");
			} else {
				sql.append(" ) ) ");
			}

			if (arr.size() > 0) {
				for (int k = 0; k < arr.size(); k++) {
					sql.append(" or d.array LIKE '" + arr.get(k) + "' ");
				}
				sql.append(" ) ");
			}
			count++;

			// 如果不存在 o and和 存在s and 和o or ,s and 和o or是并列关系
			if (oAndArr.size() == 0 && oOrArr.size() > 0 && i == 0) {
				sql.append("JOIN bas_vocab_dyad_search m" + count + " ON d.id = m" + count + ".id and ");
				if (arr.size() > 0) {
					sql.append(" ( ");
				}
				sql.append("( ( m" + count + ".property = 'oa' or m" + count + ".property = 'o' ) and ( ");
				for (int j = 0; j < oOrArr.size(); j++) {
					if (j == 0) {
						sql.append(" m" + count + ".element like '" + oOrArr.get(j) + "' ");
					} else {
						sql.append(" or m" + count + ".element like '" + oOrArr.get(j) + "' ");
					}
				}
				sql.append(" ) ) ");
				if (arr.size() > 0) {
					for (int k = 0; k < arr.size(); k++) {
						sql.append(" or d.array LIKE '" + arr.get(k) + "' ");
					}
					sql.append(" ) ");
				}
				count++;
			}
		}

		// 如果不存在and只存在or列表
		if (oAndArr.size() == 0 && sAndArr.size() == 0 && (sOrArr.size() > 0 || oOrArr.size() > 0)) {
			sql.append("JOIN bas_vocab_dyad_search m" + count + " ON d.id = m" + count + ".id and ");
			if (arr.size() > 0) {
				sql.append(" ( ");
			}
			if (sOrArr.size() > 0) {
				if (oOrArr.size() > 0) {
					sql.append(" ( ");
				}
				sql.append("( ( m" + count + ".property = 's' or m" + count + ".property = 'si' ) and ( ");
				for (int i = 0; i < sOrArr.size(); i++) {
					if (i != 0) {
						sql.append(" or ");
						sql.append("m" + count + ".element like '" + sOrArr.get(i) + "'");
					} else {
						sql.append("m" + count + ".element like '" + sOrArr.get(i) + "'");
					}
				}
				sql.append(" ) ) ");
			}
			if (oOrArr.size() > 0) {
				if (sOrArr.size() > 0) {
					sql.append(" or ");
				}
				sql.append("( ( m" + count + ".property = 'oa' or m" + count + ".property = 'o' ) and ( ");
				for (int i = 0; i < oOrArr.size(); i++) {
					if (i != 0) {
						sql.append(" or ");
						sql.append("m" + count + ".element like '" + oOrArr.get(i) + "'");
					} else {
						sql.append("m" + count + ".element like '" + oOrArr.get(i) + "'");
					}
				}
				sql.append(" ) ) ");
				if (sOrArr.size() > 0) {
					sql.append(" ) ");
				}
			}
			if (arr.size() > 0) {
				for (int k = 0; k < arr.size(); k++) {
					sql.append(" or d.array LIKE '" + arr.get(k) + "' ");
				}
				sql.append(" ) ");
			}
			count++;
		}
		// 如果只有%的词
		if (StringUtils.isBlank(sql.toString()) && arr.size() > 0) {
			sql.append("JOIN bas_vocab_dyad_search m" + count + " ON d.id = m" + count + ".id and ");
			sql.append(" ( ");
			for (int k = 0; k < arr.size(); k++) {
				if (k != 0) {
					sql.append(" or d.array LIKE '" + arr.get(k) + "' ");
				} else {
					sql.append(" d.array LIKE '" + arr.get(k) + "' ");
				}
			}
			sql.append(" ) ");
			count++;
		}

		return sql.toString();
	}

	private void getDataO(String oWord, String oKey, Map<String, Object> vmMap, List<String> oAndArr,
			List<String> oOrArr, List<String> arr, String exactSearchFlag) {
		String oWord1 = "";
		String oWord2 = "";
		String key = "";
		List<String> oWordForVm = new ArrayList<>();
		// 搜索o小词
		String[] oWords = oWord.split("\\|");
		String[] oKeys = oKey.split("\\|");
		key = oKeys[0];
		for (int i = 0; i < oWords.length; i++) {
			// 前台展示使用,表示第一排的小词o搜索词
			if (i == 0) {
				oWord1 = oWords[i];
			} else if (i == 1) {
				oWord2 = oWords[i];
			}
			// 表示第二排的小词o搜索词搜索词
			if (i != 0 && i != 1) {
				oWordForVm.add(oWords[i] + "_" + oKeys[i - 1]);
			}

			if (StringUtils.isNotBlank(oWords[i]) && !oWords[i].contains("%")) {
				// 第一个词肯定是小词o 并且是and的
				if (i == 0) {
					// 表示小词o 运算and的集合 ,用于SQL查询
					if (StringUtils.equalsIgnoreCase("1", exactSearchFlag)) {
						oAndArr.add(oWords[i]);
					} else {
						oAndArr.add("%" + oWords[i] + "%");
					}
				} else if (StringUtils.equalsIgnoreCase(oKeys[i - 1], "or")) {
					if (StringUtils.equalsIgnoreCase("1", exactSearchFlag)) {
						oOrArr.add(oWords[i]);
					} else {
						oOrArr.add("%" + oWords[i] + "%");
					}
				} else if (StringUtils.equalsIgnoreCase(oKeys[i - 1], "and")) {
					// 表示小词o 运算and的集合 ,用于SQL查询
					if (StringUtils.equalsIgnoreCase("1", exactSearchFlag)) {
						oAndArr.add(oWords[i]);
					} else {
						oAndArr.add("%" + oWords[i] + "%");
					}
				}
			} else if (StringUtils.isNotBlank(oWords[i]) && oWords[i].contains("%")) {
				if (StringUtils.equalsIgnoreCase("1", exactSearchFlag)) {
					arr.add(oWords[i]);
				} else {
					arr.add("%" + oWords[i] + "%");
				}
			}
		}
		vmMap.put("oWord1", oWord1);
		vmMap.put("oWord2", oWord2);
		vmMap.put("key", key);
		vmMap.put("oWordForVm", oWordForVm);
	}

	private void getDataS(String sWord, String sKey, Map<String, Object> vmMap, List<String> arr, List<String> sOrArr,
			List<String> sAndArr, String exactSearchFlag) {
		String sWord1 = "";
		String key2 = "";
		List<String> sWordForVm = new ArrayList<>();
		// 标准词搜索
		// 如果不是这些类型则按原来规则来

		// 搜索小词s
		String[] sWords = sWord.split("\\|");
		String[] sKeys = sKey.split("\\|");
		// 用于前台显示的展示词(第一个)
		key2 = sKeys[0];
		sWord1 = sWords[0];
		for (int i = 0; i < sWords.length; i++) {
			// 由于拿除了第一个展示词以外的词
			if (i != 0) {
				sWordForVm.add(sWords[i] + "_" + sKeys[i]);
			}
			if (StringUtils.isNotBlank(sWords[i]) && !sWords[i].contains("%")) {
				if (StringUtils.equalsIgnoreCase(sKeys[i], "or")) {
					// 表示小词s 运算or的集合 ,用于SQL查询
					if (StringUtils.equalsIgnoreCase("1", exactSearchFlag)) {
						sOrArr.add("%," + sWords[i] + ",%");
					} else {
						sOrArr.add("%" + sWords[i] + "%");
					}
				} else if (StringUtils.equalsIgnoreCase(sKeys[i], "and")) {
					if (StringUtils.equalsIgnoreCase("1", exactSearchFlag)) {
						sAndArr.add("%," + sWords[i] + ",%");
					} else {
						sAndArr.add("%" + sWords[i] + "%");
					}
				}
			} else if (StringUtils.isNotBlank(sWords[i]) && sWords[i].contains("%")) {
				if (StringUtils.equalsIgnoreCase("1", exactSearchFlag)) {
					arr.add(sWords[i]);
				} else {
					arr.add("%" + sWords[i] + "%");
				}
			}
		}
		vmMap.put("sWord1", sWord1);
		vmMap.put("key2", key2);
		vmMap.put("sWordForVm", sWordForVm);

	}

	@SuppressWarnings("unchecked")
	public ModelAndView list(String startStr, String typeKey, String exactSearchFlag, String flagKey,
			String countPerPageStr, String keysRelation, String disPlayFlag, String replaceFlag, String mergeFlag,
			String labelFlag, String oWord, String oKey, String sWord, String sKey, String arrayKey, String arrayKey2) {

		boolean vocabularyPageFlag = flagKey == null || flagKey.equals("-1");

		Map<String, Object> param = new HashMap<>();
		if (arrayKey != null && !arrayKey.isEmpty()) {
			if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
				param.put("array", arrayKey);
			} else {
				param.put("array", "%" + arrayKey + "%");
			}
			vocabularyPageFlag = false;
		}
		if (arrayKey2 != null && !arrayKey2.isEmpty()) {
			if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
				param.put("array2", arrayKey2);
			} else {
				param.put("array2", "%" + arrayKey2 + "%");
			}
			vocabularyPageFlag = false;
		}
		List<String> oAndArr = new ArrayList<>();
		List<String> sAndArr = new ArrayList<>();
		List<String> oOrArr = new ArrayList<>();
		List<String> sOrArr = new ArrayList<>();
		// 含有百分号
		List<String> arr = new ArrayList<>();

		// 记录word和key前台显示
		Map<String, Object> vmMap = new HashMap<>();
		// 判断是否是通过小词o 和小词s 进行搜索
		// 并且获取分类的词
		// 判断类型必须为o和s才能进行o和s的搜索
		if (StringUtils.equals("o+s", typeKey)
				&& ((StringUtils.isNotBlank(oWord) && StringUtils.isNotBlank(oWord.replace("|", "")))
						|| (StringUtils.isNotBlank(sWord) && StringUtils.isNotBlank(sWord.replace("|", ""))))) {
			vocabularyPageFlag = false;
			// 按AND和or归类
			if (typeKey.indexOf("o") > -1) {
				// 搜索o
				getDataO(oWord, oKey, vmMap, oAndArr, oOrArr, arr, exactSearchFlag);
			}
			// s小词可能为空
			if (StringUtils.isNotBlank(sKey.replace("|", "")) && StringUtils.isNotBlank(sWord.replace("|", ""))) {
				// 搜索小词s
				getDataS(sWord, sKey, vmMap, arr, sOrArr, sAndArr, exactSearchFlag);
			}
		}
		if (StringUtils.equals("o+s", typeKey) && (oAndArr.size() > 0 || sAndArr.size() > 0 || oOrArr.size() > 0
				|| sOrArr.size() > 0 || arr.size() > 0)) {
			param.put("arrayOS", getSqlForOSSearch(oAndArr, sAndArr, oOrArr, sOrArr, arr));
		}

		if (!vocabularyPageFlag && "or".equals(keysRelation)) {
			param.put("keysRelation", keysRelation);
		}
		if (StringUtils.isNotBlank(disPlayFlag)) {
			param.put("disPlayFlag", disPlayFlag);
		}
		if (StringUtils.isNotBlank(replaceFlag)) {
			param.put("replaceFlag", replaceFlag);
		}
		if (StringUtils.isNotBlank(mergeFlag)) {
			param.put("mergeFlag", mergeFlag);
		}
		if (StringUtils.isNotBlank(labelFlag)) {
			param.put("labelFlag", labelFlag);
		}
		if (typeKey != null && !typeKey.isEmpty()) {
			param.put("type", typeKey);
			if ("p+p".equals(typeKey)) {
				vocabularyPageFlag = false;
			}
		}
		if (flagKey != null && !flagKey.isEmpty()) {
			param.put("flag", flagKey);
		}

		int totalSize = 0, start = 0, endPage = 0, startIndex = 0;
		String orderVocabulary = "";

		List<VocabDyadStd> list = new ArrayList<>();
		if (!vocabularyPageFlag) {
			// 如果是已校验或p+p或查询的数据则用通用的列表展示
			if (StringUtils.equals("o+s", typeKey)) {
				totalSize = vocabDyadStdDao.retrieveSizeByOs(param);
			} else {
				totalSize = vocabDyadStdDao.retrieveSize(param);
			}
			LOGGER.info("List total size=" + totalSize);

			Map<String, Integer> pageNo = GetListUtil.getPageNoParam(totalSize, startStr);
			if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
				int countPerPage = Integer.parseInt(countPerPageStr);
				pageNo = GetListUtil.getPageNoParam(totalSize, startStr, countPerPage);

				param.put("countPerPage", countPerPage);
			}

			endPage = pageNo.get("endPage");
			start = pageNo.get("start");
			startIndex = pageNo.get("startIndex");

			if (startIndex < totalSize) {
				param.put("startIndex", startIndex);
				if (flagKey == null || flagKey.equals("-1")) {
					param.put("orderStr", "array");
				} else {
					param.put("orderStr", "synonym_flag,gmt_modified desc");
				}
				if ("p+p".equals(typeKey)) {
					param.put("orderStr", "length(part_pattern),array");
				}
				if (StringUtils.equals("o+s", typeKey)) {
					list = vocabDyadStdDao.retrieveListByOS(param);
				} else {
					list = vocabDyadStdDao.retrieveList(param);
				}
			}
		} else {
			// 获取当前页码
			endPage = vocabDyadStdDao.retrieveTotalPageNo(typeKey);
			if (endPage < 1) {
				endPage = 1;
			}
			start = startStr == null ? 1 : Integer.parseInt(startStr);
			if (start > endPage) {
				start = endPage;
			}

			// 获取页码对应的排序字段
			param.put("pageNo", start);
			orderVocabulary = vocabDyadStdDao.retrievePageOrderVocabulary(param);

			if (orderVocabulary != null && !orderVocabulary.isEmpty()) {
				// 根据页码获取列表
				param.put("orderStr", "order_vocabulary,array");
				param.put("orderVocabulary", orderVocabulary);
				list = vocabDyadStdDao.retrieveList(param);
			}
		}
		List<VocabDyadStd> removeList = new ArrayList<>();
		// 将列表中的同义词拆出来放在列表中，维护例句；如果是o+o则需要将是否结合s的数据进行维护
		for (VocabDyadStd dyad : list) {

			List<String> synonymList = new ArrayList<>();
			if (dyad.getSynonym() != null && !dyad.getSynonym().isEmpty()) {
				for (String synonym : dyad.getSynonym().split((char) 1 + "")) {
					synonymList.add(synonym);
				}
			}
			dyad.setSynonymList(synonymList);

			dyad.setShowSentence(dyad.getSentence().split((char) 1 + "")[0]);

			dyad.setSentence(dyad.getSentence().replace((char) 1, '\n'));

			if (!"o+s".equals(typeKey)) {
				setRemove(dyad, dyad.getArray(), dyad.getPartPattern());
			}
			if ("o+o".equals(typeKey) ||"o+de".equals(typeKey)) {
				setCombineSElement(dyad);
			}
		}
		list.removeAll(removeList);

		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("arrayKey", "标准词");
		showSearch.put("arrayKey2", "标准词");

		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, null);
		map.put("showSearch", showSearch);
		map.put("orderVocabulary", orderVocabulary);
		map.put("keysRelation", keysRelation);
		map.put("removeButtonFlag",
				"o+o".equals(typeKey) || "o+oa".equals(typeKey) || "o+in".equals(typeKey) || "o+in+s".equals(typeKey));
		map.put("submitFlag", SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_DYAD_SUBMIT_P_P));
		map.put("mergeTrueFlag", SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_DYAD_MERGE_TRUE_DYAD));
		// 前台显示
		map.put("oWord1", vmMap.get("oWord1") == null ? "" : vmMap.get("oWord1"));
		map.put("oWord2", vmMap.get("oWord2") == null ? "" : vmMap.get("oWord2"));
		map.put("key", vmMap.get("key") == null ? "" : vmMap.get("key"));
		map.put("oWordForVm", vmMap.get("oWordForVm") == null ? new ArrayList<>() : vmMap.get("oWordForVm"));
		map.put("sWordForVm", vmMap.get("sWordForVm") == null ? new ArrayList<>() : vmMap.get("sWordForVm"));
		map.put("key2", vmMap.get("key2") == null ? "" : vmMap.get("key2"));
		map.put("sWord1", vmMap.get("sWord1") == null ? "" : vmMap.get("sWord1"));
		if (vmMap.get("oWordForVm") != null) {
			List<String> oWordForVm = (List<String>) vmMap.get("oWordForVm");
			if (oWordForVm != null && oWordForVm.size() > 0) {
				map.put("oWordDisPlay", '1');
			}
		}
		if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
			map.put("countPerPage", countPerPageStr);
		}

		return new ModelAndView("vocab/dyad_index", map);
	}

	private void setCombineSElement(VocabDyadStd dyad) {

		List<VocabDyadRemoveSplit> splitList = new ArrayList<>();

		String[] vocabs = dyad.getArray().substring(1).split(",");
		String[] props = dyad.getPartPattern().substring(1).split(",");
		String[] combines = dyad.getCombineS().substring(1).split(",");

		for (int i = 0; i < vocabs.length; i++) {
			VocabDyadRemoveSplit split = new VocabDyadRemoveSplit();
			split.setVocabulary(vocabs[i]);
			split.setProperty(props[i]);
			split.setFlag(Integer.parseInt(combines[i]));

			splitList.add(split);
		}
		dyad.setCombineSList(splitList);
	}

	private void setRemove(VocabDyadStd dyad, String array, String partPattern) {

		String type = dyad.getType();

		List<VocabDyadRemoveSplit> splitList = new ArrayList<>();
		String resultArray = ",";
		String resultPattern = ",";

		String[] vocabs = array.substring(1).split(",");
		String[] props = partPattern.substring(1).split(",");
		for (int i = 0; i < vocabs.length; i++) {
			VocabDyadRemoveSplit split = new VocabDyadRemoveSplit();
			split.setVocabulary(vocabs[i]);
			split.setProperty(props[i]);
			if (type.indexOf("in") > -1 && props[i].indexOf("o") > -1) {
				split.setFlag(BaseContants.FLAG_YES);
			} else {
				split.setFlag(BaseContants.FLAG_NO);
				resultArray += vocabs[i] + ",";
				resultPattern += props[i] + ",";
			}

			splitList.add(split);
		}
		dyad.setSplitList(splitList);
		dyad.setResultArray(resultArray);
		dyad.setResultPattern(resultPattern);
	}

	public ReturnData checkPage(String checkedIds, String unCheckedIds, String type, User user) {

		// 判断用户是否实习生，是实习生需要维护check_id字段和工作量数据，非实习生需要维护synonym_flag字段
		Long checkId = null;
		Integer synonymFlag = null;
		if (RoleID.ADMIN.equals(user.getRole())) {
			synonymFlag = 1;
		} else{
			//所有不是管理员的~都要记录~操作了多少条记录和check_id
			checkId = user.getUserId();

			int count1 = checkedIds == null || checkedIds.isEmpty() ? 0 : checkedIds.split(",").length;
			int count2 = unCheckedIds == null || unCheckedIds.isEmpty() ? 0 : unCheckedIds.split(",").length;

			userRecordService.addUpUserRecord(user.getUserId(), count1 + count2);
		}

		// 将勾选的数据维护成正确的
		if (checkedIds != null && !checkedIds.isEmpty()) {
			vocabDyadStdDao.updateStdFlagByIds(checkedIds, BaseContants.FLAG_RIGHT, user.getUserId(), checkId,
					synonymFlag);

			if ("p+p".equals(type)) { // 如果是p+p的则需要将p+o中相关的由系统判定为错误的数据转移到未校验
				vocabDyadStdDao.resetPOFlagByPP(checkedIds, user.getUserId());
			}
			
			// 提交的这批数据中如果历史正确数据有元素同义词都相同的则合并
			vocabDyadStdDao.mergeSynonymByRight(checkedIds);
		}

		// 将未勾选的数据维护成错误的
		if (unCheckedIds != null && !unCheckedIds.isEmpty()) {
			vocabDyadStdDao.updateStdFlagByIds(unCheckedIds, BaseContants.FLAG_WRONG, user.getUserId(), checkId,
					synonymFlag);

			if ("o+oa".equals(type)) { // 如果是o+oa则需要将包含该o+oa的未校验数据判定为错误
				vocabDyadStdDao.checkDyadBySubWrongIds(unCheckedIds, "'o+in','o+in+s','p+o','o+s'");
			} else if ("o+in".equals(type)) { // 如果是o+in则需要将未校验o+in+s中的包含o+in的数据判定为错误
				vocabDyadStdDao.checkDyadBySubWrongIds(unCheckedIds, "'o+in+s'");
			}
		}
		// 维护o+s的搜索相关表
		if ("o+s".equals(type)) {
			vocabDyadInitService.initOSSearch();
		}
		
		// 维护排序分页数据
		vocabDyadInitService.init7();
		return ReturnUtil.success();
	}

	public ReturnData changeStd(String id, String dyad, User user, String type, Boolean isTest) {

		// 从dyad中获取array和partPattern
		String array = dyad.split("\\(")[0];
		String partPattern = dyad.split("\\(")[1].replace(")", "");

		if (isTest) {

			// 根据id更改测试数据中的array和partPattern
			vocabDyadStdDao.updateDyadStdTest(id, array, partPattern, user.getUserId());

		} else {
			// 根据id更改std的array和partPattern
			vocabDyadStdDao.updateDyadStd(id, array, partPattern, user.getUserId());

			// 如果排序字段是新增的则需要将该排序字段维护到排序分页数据中
			if (vocabDyadStdDao.isNewOrderVocabulary(id)) {
				vocabDyadStdDao.updatePageByStdId(id);
			}
		}

		return ReturnUtil.success();
	}

	public ReturnData deleteSynonym(String dyad, String type, User user) {

		// 从dyad中获取array和partPattern
		String array = dyad.split("\\(")[0];
		String partPattern = dyad.split("\\(")[1].replace(")", "");

		// 创建一个新的标准词
		Long stdId = vocabDyadStdDao.insertStd(type, array, partPattern, user.getUserId());

		vocabDyadDao.updateStdByDyad(array, partPattern, stdId);

		// 如果排序字段是新增的则需要将该排序字段维护到排序分页数据中
		String id = stdId + "";
		if (vocabDyadStdDao.isNewOrderVocabulary(id)) {
			vocabDyadStdDao.updatePageByStdId(id);
		}

		return ReturnUtil.success();
	}

	public ReturnData stdMerge(String ids, User user,String type) {

		// 转移该批二元组到频数最高的标准词下
		vocabDyadDao.mergeStdIdByCnt(ids, user.getUserId());

		// 将没有同义词的标准词删除
		vocabDyadStdDao.deleteNoSynonym();

		if(StringUtils.equalsIgnoreCase("p+o", type)){
			vocabDyadPositionService.init();
		}
		return ReturnUtil.success();
	}

	public ReturnData stdAddRemove(String id, String resultArray, String resultPattern, boolean confirmFlag)
			throws Exception {

		if (!confirmFlag) {
			// 如果是第一次提交，查询是否有相同的remove
			VocabDyadRemove existRemove = vocabDyadRemoveDao.retrieveCheckedObjectByDyadStd(id);
			if (existRemove != null) {
				String msg = "该二元组remove已存在：[#array#(#partPattern#)]->[#resultArray#(#resultPattern#)]；是否替换？";
				msg = msg.replace("#array#", existRemove.getArray());
				msg = msg.replace("#partPattern#", existRemove.getPartPattern());
				msg = msg.replace("#resultArray#", existRemove.getResultArray());
				msg = msg.replace("#resultPattern#", existRemove.getResultPattern());

				ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
				rc.setDesc(msg);
				return ReturnUtil.fail(rc);
			}
		}

		vocabDyadRemoveDao.deleteByDyadStd(id);
		// 根据标准词和结果词增加一个remove数据
		vocabDyadRemoveDao.addRemoveByStdId(id, resultArray, resultPattern);

		// 获取该remove（本来是在新增的时候直接获取id，可惜这个ID获取出来为0）
		VocabDyadRemove remove = vocabDyadRemoveDao.retrieveCheckedObjectByDyadStd(id);

		// 初始化remove的标准词
		vocabDyadInitDao.initRemoveStd(remove.getId());

		return ReturnUtil.success();
	}

	public ReturnData stdPreFlag(String id, String preFlag, User user, Boolean isTest,String type) {

		// 根据id更改二元组标准词的预判标志
		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setPreFlag(Integer.parseInt(preFlag));
		dyad.setModifierId(user.getUserId());

		if (isTest) {
			vocabDyadStdDao.updateTest(dyad);
		} else {
			// 如果是o+de勾选为正确，则带走所有的de，若错误，不带走de
			if(VocabConstant.DYAD_O_DE.equals(type)){
				// 获取该id的
				VocabDyadStd std = vocabDyadStdDao.retrieveObjectById(Long.parseLong(id));
				if(BaseContants.DISABLE_VALID.equals(preFlag)){
					dyad.setCombineS(std.getCombineS().replace(BaseContants.FLAG_NO.toString(),BaseContants.FLAG_YES.toString()));
				}else{
					String[] combines = std.getCombineS().substring(1,std.getCombineS().length()-1).split(",");
					String[] partpattern = std.getPartPattern().substring(1,std.getPartPattern().length()-1).split(",");
					List<String> combine = new ArrayList<>();
					for(int i= 0 ; i<combines.length;i++){
						if(StringUtils.equals(partpattern[i],VocabConstant.ELEMENT_DEGREE)){
							combine.add(BaseContants.FLAG_NO.toString());
						}else{
							combine.add(BaseContants.FLAG_YES.toString());
						}
					}
					dyad.setCombineS(BusinessUtil.getStringFromListBySeparator(combine, ","));
				}
			}
			vocabDyadStdDao.update(dyad);
		}

		return ReturnUtil.success();
	}

	/**
	 * 标准词中提交已完成的基础二元组，根据症状分词生成下一步的二元组
	 * 
	 * @param type
	 * @return
	 */
	public ReturnData stdSubmitBase(String type) {
		LOGGER.info("Dyad submit base, type is " + type);

		if ("p+p".equals(type)) {
			stdSubmitPP();
		} else if ("p+o".equals(type)) {
			stdSubmitPO();
		} else if ("o+o".equals(type)) {
			stdSubmitOO();
		}
		return ReturnUtil.success();
	}

	/**
	 * 提交o+o的二元组，生成o+s数据
	 */
	private void stdSubmitOO() {

		if (!SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_DYAD_SUBMIT_O_O)) {

			// 提交o+o设置为运行中
			SubmitStatus.addSubmitRecords(SubmitStatus.TYPE_DYAD_SUBMIT_O_O);

			// 获取o和oa的标准词对应map，用来维护排序字段
			Map<String, String> sStdMap = getElementStdMapByProperty("s");

			// 症状中没有p且只有一个o的o+s直接通过sql生成到pre
			vocabDyadDao.initPreOS();
			LOGGER.info("Dyad submit o+o, init o+s pre step 1 success!");

			// 记录符合条件预备词
			List<VocabDyadPre> resultList = new ArrayList<>();

			// 获取由多个o组成的核心词列表
			List<String> multiOCombineSPreList = vocabDyadDao.retrieveMultiOCombineS();

			// 症状中有多个o的情况需要通过o+o来判断获取
			// 获取症状中有多个o且带s的数据
			List<Map<String, String>> multiOSPreList = vocabDyadDao.retrieveMultiOSPre();
			for (Map<String, String> multiOSPre : multiOSPreList) {
				resultList.add(getPreByMultiOSPre(multiOSPre, multiOCombineSPreList, sStdMap));
			}
			LOGGER.info("Dyad submit o+o, init o+s pre step 2 success!");

			// 将准备好的预备词添加到数据库中
			vocabDyadInitDao.batchInsertPre(resultList);
			LOGGER.info("Dyad submit o+o, result pre insert success, size is " + resultList.size());

			// 通过sql将pre生成dyad
			vocabDyadDao.initOSDyadByPre();
			vocabDyadInitDao.initDyadSentence();
			LOGGER.info("Dyad submit o+o, init o+s dyad by pre success!");

			// 将页面排序初始化
			vocabDyadInitService.init7();

			LOGGER.info("Dyad submit o+o success!");

			SubmitStatus.removeSubmitRecords(SubmitStatus.TYPE_DYAD_SUBMIT_O_O);
		}
	}

	private VocabDyadPre getPreByMultiOSPre(Map<String, String> multiPOSPre, List<String> multiOCombineSPreList,
			Map<String, String> sStdMap) {
		String[] symptomArrays = multiPOSPre.get("symptom_array").substring(1).split(","); // 完整症状分词
		String[] partPatterns = multiPOSPre.get("part_pattern").substring(1).split(","); // 完整症状分词属性
		String[] stdArrays = multiPOSPre.get("std_array").substring(1).split(","); // 完整症状分词标准词
		String symptomId = multiPOSPre.get("id"); // 症状的id

		String resultArray = ",";
		String resultPartPattern = ",";
		String resultStdArray = ",";
		String resultOrderVocabulary = "";
		for (int i = 0; i < partPatterns.length; i++) {
			if ("o".equals(partPatterns[i]) && resultOrderVocabulary.isEmpty()) {
				resultOrderVocabulary = stdArrays[i];
			}

			// 如果s在o完成之前出现，则先将s加入
			if ("s".equals(partPatterns[i])) {
				if (",".equals(resultArray)) {
					resultArray += symptomArrays[i] + ",";
					resultPartPattern += "s,";
					resultStdArray += stdArrays[i] + ",";
				}
			} else {
				// 如果进入o，则判断在这之后所有的o组合起来是否有效，如果有效，则将之后所有的元素都组合起来并结束（如果s在这之后也会组合进来）
				String oStdTemp = ",";
				int oCount = 0;
				String arrayTemp = "", partPatternTemp = "", stdTemp = "";
				for (int j = i; j < partPatterns.length; j++) {
					if (partPatterns[j].indexOf("o") >= 0) {
						oCount++;
						oStdTemp += stdArrays[j] + ",";
					}
					if (resultOrderVocabulary.isEmpty() && "o".equals(partPatterns[j])) {
						resultOrderVocabulary = stdArrays[j];
					}
					arrayTemp += symptomArrays[j] + ",";
					partPatternTemp += partPatterns[j] + ",";
					stdTemp += stdArrays[j] + ",";
				}
				if (multiOCombineSPreList.contains(oStdTemp) || oCount == 1) {
					resultArray += arrayTemp;
					resultPartPattern += partPatternTemp;
					resultStdArray += stdTemp;

					break;
				}
			}
		}

		if (resultOrderVocabulary.isEmpty()) {
			// 如果还没有排序字段，表示这个二元组中没有o，则用二元组中最后一个oa来做排序字段
			for (int i = partPatterns.length - 1; i >= 0; i--) {
				if (partPatterns[i].indexOf("o") >= 0) {
					resultOrderVocabulary = stdArrays[i];
				}
			}
		}

		VocabDyadPre OOPre = new VocabDyadPre();
		OOPre.setArray(resultArray);
		OOPre.setPartPattern(resultPartPattern);
		OOPre.setSymptomId(Long.parseLong(symptomId));
		OOPre.setOrderVocabulary(resultOrderVocabulary);
		OOPre.setStdArray(resultStdArray);
		OOPre.setStdSynonym(resultStdArray);
		OOPre.setType("o+s");

		return OOPre;
	}

	/**
	 * 提交p+o的二元组，生成去p后的o+o数据
	 */
	private void stdSubmitPO() {

		if (!SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_DYAD_SUBMIT_P_O)) {

			// 提交p+o设置为运行中
			SubmitStatus.addSubmitRecords(SubmitStatus.TYPE_DYAD_SUBMIT_P_O);

			// 症状中o+o直接通过sql生成到pre
			vocabDyadDao.initPreOO();
			LOGGER.info("Dyad submit p+o, init o+o pre step 1 success!");

			// 通过sql预生成pre2
			vocabDyadDao.initOODyadPre2();
			LOGGER.info("Dyad submit p+o, init p+o dyad by pre success!");

			// 通过remove数据简化o+o并初始化到dyad
			// 获取o+o的所有pre2
			Map<String, Object> param = new HashMap<String, Object>();
			param.put("types", "'o+o'");
			List<VocabDyadPre> preList = vocabDyadInitDao.retrieveRemovePreList(param);
			LOGGER.info("Dyad submit p+o, get pre2 list success,size is " + preList.size());
			// 获取remove的数据
			Map<String, Object> param1 = new HashMap<>();
			param1.clear();
			param1.put("removeFlag", BaseContants.FLAG_YES);
			param1.put("types", "'o+oa'");
			List<VocabDyadRemove> removeList = vocabDyadRemoveDao.retrieveList(param1);
			// 根据remove列表的规则将pre列表进行处理
			vocabDyadInitService.removePreList(preList, removeList);

			// 将pre3保存到数据库(5000条一批次)
			int start = 0, end, size = preList.size();
			List<VocabDyadPre> tempList;
			LOGGER.info("Insert into pre3 start!");
			while (start < size) {
				if (start + 5000 < size) {
					end = start + 5000;
				} else {
					end = size;
				}
				tempList = preList.subList(start, end);
				vocabDyadInitDao.batchInsertPre3(tempList);
				start += 5000;
			}

			// 将pre3初始化到dyad
			vocabDyadDao.initOODyadByPre3();

			// 将dyad的例句初始化
			vocabDyadInitDao.initDyadSentence();

			// 将页面排序初始化
			vocabDyadInitService.init7();

			LOGGER.info("Dyad submit p+o success!");

			SubmitStatus.removeSubmitRecords(SubmitStatus.TYPE_DYAD_SUBMIT_P_O);
		}
	}

	/**
	 * 提交p+p的二元组，生成前后相连的p+o(oa)数据；
	 */
	private void stdSubmitPP() {

		if (!SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_DYAD_SUBMIT_P_P)) {

			// 提交p+p设置为运行中
			SubmitStatus.addSubmitRecords(SubmitStatus.TYPE_DYAD_SUBMIT_P_P);

			// 初始化pre表，简单的p+o直接由sql生成
			vocabDyadDao.initPrePO();
			LOGGER.info("Dyad submit p+p, init p+o pre step 1 success!");

			// 获取错误的P+P，不在错误的P+P中就默认为正确的
			List<String> wrongPPList = vocabDyadDao.retrieveWrongPPArray();
			LOGGER.info("Dyad submit p+p, retrieve p+p wrong array size is " + wrongPPList.size());

			// 复杂的p+o通过代码拆分生成
			List<VocabDyadPre> resultList = new ArrayList<>();
			List<VocabDyadPre> complexList = vocabDyadDao.retrieveComplexPOPre();
			for (VocabDyadPre complex : complexList) {
				resultList.addAll(getPOPreByComplex(complex, wrongPPList));
			}
			LOGGER.info("Dyad submit p+p, init p+o pre step 2 success!");

			// 将准备好的预备词添加到数据库中
			vocabDyadInitDao.batchInsertPre(resultList);
			LOGGER.info("Dyad submit p+p, result pre insert success, size is " + resultList.size());

			// 通过sql将pre数据添加到二元组中
			vocabDyadDao.initPODyadByPre();
			vocabDyadInitDao.initDyadSentence();
			LOGGER.info("Dyad submit p+p, init p+o dyad by pre success!");

			// 将页面排序初始化
			vocabDyadInitService.init7();
			LOGGER.info("Dyad submit p+p success!");

			SubmitStatus.removeSubmitRecords(SubmitStatus.TYPE_DYAD_SUBMIT_P_P);
		}
	}

	/**
	 * 根据一个复杂的p+o拆解出单个p+o的列表
	 * 
	 * @param complex
	 * @param wrongPPList
	 * @return
	 */
	private List<VocabDyadPre> getPOPreByComplex(VocabDyadPre complex, List<String> wrongPPList) {

		List<VocabDyadPre> list = new ArrayList<>();
		String[] words = complex.getArray().substring(1).split(",");
		String[] properties = complex.getPartPattern().substring(1).split(",");
		String[] stds = complex.getStdArray().substring(1).split(",");
		boolean splitFlag = false;
		List<String> pTemp = new ArrayList<>();
		List<String> pStdTemp = new ArrayList<>();
		String oTemp = "";
		String oStdTemp = "";
		String oPropertyTemp = "";

		for (int i = 0; i < words.length; i++) {
			if (properties[i].equals("p")) {
				// 属性是p的元素则累加，并判断该当前p+p是否是错误的
				pTemp.add(words[i]);
				pStdTemp.add(stds[i]);
				if (!splitFlag && wrongPPList.contains(getWordStrByList(pTemp))) {
					splitFlag = true;
				}

				// 如果p是最后一个词语了则需维护最后一个p+o
				if (i == words.length - 1) {
					list.addAll(getPOListByWords(pTemp, oTemp, oPropertyTemp, false, 2, complex, pStdTemp, oStdTemp,
							wrongPPList));
				}
			} else {
				// 属性是o或者oa，如果有上一个o和p则先维护
				if (!oTemp.isEmpty() && !pTemp.isEmpty()) {
					list.addAll(getPOListByWords(pTemp, oTemp, oPropertyTemp, splitFlag, 2, complex, pStdTemp, oStdTemp,
							wrongPPList));
				}

				// 将属性修改为当前的o
				oTemp = words[i];
				oStdTemp = stds[i];
				oPropertyTemp = properties[i];

				// 如果之前有p则维护当前o的p+o
				if (!pTemp.isEmpty()) {
					// 如果是第一个前面有p的o，则不需要拆分
					if (oTemp.isEmpty()) {
						splitFlag = false;
					}
					list.addAll(getPOListByWords(pTemp, oTemp, oPropertyTemp, splitFlag, 1, complex, pStdTemp, oStdTemp,
							wrongPPList));
				}

				// 维护好之后清空之前的p
				pTemp = new ArrayList<>();
				pStdTemp = new ArrayList<>();
				splitFlag = true;
			}
		}
		return list;
	}

	/**
	 * 根据p和o的词语以及相关属性获取最终p+o的数据
	 * 
	 * @param pTemp
	 * @param oTemp
	 * @param splitFlag
	 * @param position:1表示p在o之前；2表示p在o之后
	 * @param complex
	 * @param oStdTemp
	 * @param pStdTemp
	 * @return
	 */
	private List<VocabDyadPre> getPOListByWords(List<String> pTemp, String oTemp, String oPropertyTemp,
			boolean splitFlag, int position, VocabDyadPre complex, List<String> pStdTemp, String oStdTemp,
			List<String> wrongPPList) {
		List<String> ppStrList = new ArrayList<>();
		List<String> ppStdStrList = new ArrayList<>();

		if (!splitFlag || pTemp.size() == 1) {
			ppStrList.add(getWordStrByList(pTemp));
			ppStdStrList.add(getWordStrByList(pStdTemp));
		} else if (pTemp.size() > 1) {
			for (int i = 1; i <= pTemp.size() - 1; i++) {
				if (position == 1) {
					ppStrList.add(getWordStrByList(pTemp.subList(pTemp.size() - i, pTemp.size())));
					ppStdStrList.add(getWordStrByList(pStdTemp.subList(pStdTemp.size() - i, pStdTemp.size())));
				} else {
					ppStrList.add(getWordStrByList(pTemp.subList(0, i)));
					ppStdStrList.add(getWordStrByList(pStdTemp.subList(0, i)));
				}
			}
		}

		List<VocabDyadPre> resultList = new ArrayList<>();
		for (int i = 0; i < ppStrList.size(); i++) {
			String pp = ppStrList.get(i);
			String ppStd = ppStdStrList.get(i);

			if (wrongPPList.contains(pp) || wrongPPList.contains(ppStd)) {
				continue;
			}

			VocabDyadPre temp = new VocabDyadPre();
			temp.setSymptomId(complex.getSymptomId());
			temp.setArray(position == 1 ? pp + oTemp + "," : "," + oTemp + pp);
			String partPattern = ",";
			for (int j = 0; j < pp.length() - pp.replace(",", "").length() - 1; j++) {
				partPattern += "p,";
			}
			temp.setPartPattern(position == 1 ? partPattern + oPropertyTemp + "," : "," + oPropertyTemp + partPattern);
			temp.setOrderVocabulary(oStdTemp);
			temp.setStdArray(position == 1 ? ppStd + oStdTemp + "," : "," + oStdTemp + ppStd);
			temp.setStdSynonym(temp.getStdArray());
			temp.setType("p+o");

			resultList.add(temp);
		}

		return resultList;
	}

	/**
	 * 根据词语的列表获取根据逗号分割的字符串
	 * 
	 * @param pTemp
	 * @return
	 */
	private String getWordStrByList(List<String> pTemp) {
		if (pTemp.isEmpty()) {
			return "";
		}

		StringBuilder sb = new StringBuilder(",");
		for (String p : pTemp) {
			sb.append(p);
			sb.append(",");
		}
		return sb.toString();
	}

	public ReturnData stdLabelFlag(String id, String labelFlag, User user) {

		// 根据id更改二元组标准词的分词标注问题标志
		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setLabelFlag(Integer.parseInt(labelFlag));
		dyad.setModifierId(user.getUserId());

		vocabDyadStdDao.update(dyad);

		return ReturnUtil.success();
	}

	public ReturnData stdMergeFlag(String id, String mergeFlag, User user) {

		// 根据id更改二元组标准词的分词标注问题标志
		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setMergeFlag(Integer.parseInt(mergeFlag));
		dyad.setModifierId(user.getUserId());

		vocabDyadStdDao.update(dyad);

		return ReturnUtil.success();
	}

	public ReturnData stdDisplayFlag(String id, String displayFlag, User user) {

		// 根据id更改二元组标准词的分词标注问题标志
		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setDisplayFlag(Integer.parseInt(displayFlag));
		dyad.setModifierId(user.getUserId());

		vocabDyadStdDao.update(dyad);

		return ReturnUtil.success();
	}

	public ReturnData changeSynonmy(String id, String synonmy, String typeKey) {

		if (StringUtils.isNotBlank(synonmy)) {
			Map<String, Object> param = new HashMap<>();
			param.put("flag", 0);
			param.put("vocabulary", synonmy);
			if (StringUtils.equalsIgnoreCase("p+o", typeKey) || StringUtils.equalsIgnoreCase("o+o", typeKey)) {
				param.put("property", "o");
			} else if (StringUtils.equalsIgnoreCase("s+de", typeKey)) {
				param.put("property", "s");
			} else {
				param.put("property", "si");
			}
			List<VocabElement> list = vocabElementDao.retrieveList(param);
			if (list == null || list.size() == 0) {
				ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
				rc.setDesc("该词不是正确的si 、 o 或 s小词");
				return ReturnUtil.fail(rc);
			}
		}
		// 修改元素同义词
		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setElementSynonym(synonmy);

		vocabDyadStdDao.update(dyad);

		return ReturnUtil.success();
	}

	public ReturnData stdUpdateCombineS(String id, String combineS, User user) {

		// 重置核心词规则
		recordMultiOCombineS(id, combineS);

		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setCombineS(combineS);
		dyad.setModifierId(user.getUserId());

		vocabDyadStdDao.update(dyad);

		return ReturnUtil.success();
	}

	private void recordMultiOCombineS(String id, String combineS) {
		VocabDyadStd std = vocabDyadStdDao.retrieveObjectById(Long.parseLong(id));
		String[] arrays = std.getArray().substring(1).split(",");
		String[] stdArrays = std.getStdArray().substring(1).split(",");
		String[] oldCombineSs = std.getCombineS().substring(1).split(",");
		String[] newCombineSs = combineS.substring(1).split(",");

		String resultArray = "";
		String resultStdArray = "";
		String resultCombineS = "";
		// 根据两个CombineS中哪个1比较多就以哪个为记录标准
		for (int i = newCombineSs.length - 1; i >= 0; i--) {
			if (oldCombineSs[i].equals("1") || newCombineSs[i].equals("1")) {
				resultArray = arrays[i] + "," + resultArray;
				resultStdArray = stdArrays[i] + "," + resultStdArray;
				resultCombineS = newCombineSs[i] + "," + resultCombineS;
			}
		}

		if (resultCombineS.split(",").length > 1) {
			// TODO 如果更改会造成1,0,1这样的数据则需要提醒

			// 判断最终结果是否有两个词以上，只有结果在两个词以上才进入
			resultArray = "," + resultArray;
			resultStdArray = "," + resultStdArray;
			resultCombineS = "," + resultCombineS;

			// 记录核心词更改信息
			vocabDyadStdDao.insertMultiOCombineS(resultArray, resultStdArray, resultCombineS);

			// 更改相同核心词的二元组
			vocabDyadStdDao.updateCombineSByMultiO(resultStdArray, resultCombineS);
		}
	}

	public ReturnData stdReplaceFlag(String id, String replaceFlag, User user) {

		// 根据id更改二元组标准词的是否替换标志
		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setReplaceFlag(Integer.parseInt(replaceFlag));
		dyad.setModifierId(user.getUserId());

		vocabDyadStdDao.update(dyad);

		return ReturnUtil.success();
	}

	@Autowired
	private SynonymyWordDao synonymyWordDao;

	/**
	 * 根据类型
	 * 
	 * @param property
	 * @return
	 */
	protected Map<String, String> getElementStdMapByProperty(String property) {
		Map<String, String> result = new HashMap<>();

		List<Map<String, String>> list = new ArrayList<>();
		if (property.equals("o")) {
			list = synonymyWordDao.retrieveElementSynonymO();
		} else {
			list = synonymyWordDao.retrieveElementSynonymByProperty(property);
		}
		for (Map<String, String> temp : list) {
			result.put(temp.get("word"), temp.get("std"));
		}

		return result;
	}

	public ReturnData stdUpdateSentenceOrder(String id, String sentenceOrder, User user) {

		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setSentenceOrder(sentenceOrder);
		dyad.setModifierId(user.getUserId());

		vocabDyadStdDao.update(dyad);

		return ReturnUtil.success();
	}

	/**
	 * 实习生校验正误页面
	 * 
	 * @param flagKey
	 * @param user
	 * @param resp
	 * @param req
	 * @param start
	 * @param arrayKey
	 * @param internType
	 * @return
	 * @throws Exception
	 */
	public ModelAndView internList(String flagKey, User user, HttpServletResponse resp, HttpServletRequest req,
			String start, String arrayKey, String internType) throws Exception {

		// 根据用户和权限去获取能力记录
		UserAbility ua = userAbilityService.getAbilityByUserId(user.getUserId(), user.getRole());
		if (BaseContants.FLAG_NO.equals(ua.getExamPass())) {
			// 测试失败的，进入失败页面
			return userAbilityService.incapable(resp, req);

		} else if (BaseContants.FLAG_YES.equals(ua.getExamPass())) {
			// 测试通过的，获取正式数据
			return formalData(flagKey, user, internType, start, arrayKey);

		} else {
			// 测试未完成的，获取测试数据
			return testData(flagKey, user, internType, start, arrayKey);

		}
	}

	private ModelAndView testData(String flagKey, User user, String type, String startStr, String arrayKey) {
		Map<String, Object> map = new HashMap<>();
		List<VocabDyadStd> list = new ArrayList<>();

		// 获取未校验的测试数据
		Map<String, Object> param = new HashMap<>();
		param.put("checkId", user.getUserId());
		param.put("flag", Integer.parseInt(flagKey));
		param.put("type", type);
		if (arrayKey != null && !arrayKey.isEmpty()) {
			param.put("arrayKey", "%" + arrayKey + "%");
		}

		if (!BaseContants.FLAG_NULL.equals(Integer.parseInt(flagKey))) {
			param.put("start", startStr);

			int totalSize = vocabDyadStdDao.retrieveInternTestSize(param);

			Map<String, Integer> pageNo = GetListUtil.getPageNoParam(totalSize, startStr);

			int endPage = pageNo.get("endPage");
			int start = pageNo.get("start");
			int startIndex = pageNo.get("startIndex");

			if (startIndex < totalSize) {
				param.put("startIndex", startIndex);
				param.put("orderStr", "gmt_modified desc");
				list = vocabDyadStdDao.retrieveInternTestList(param);
			}

			Map<String, String> showSearch = new LinkedHashMap<>();
			showSearch.put("arrayKey", "标准词");

			map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, null);
			map.put("showSearch", showSearch);
		} else {
			list = vocabDyadStdDao.retrieveInternTestList(param);

			if (list == null || list.isEmpty()) {
				// 如果没有未校验数据则初始化
				vocabDyadStdDao.initInternTest(param);

				// 新增后获取
				list = vocabDyadStdDao.retrieveInternTestList(param);
			}
			map.put("list", list);
		}

		arrangeList(list);

		map.put("isTest", true);

		return new ModelAndView("vocab/dyad_index", map);
	}

	private ModelAndView formalData(String flagKey, User user, String type, String startStr, String arrayKey) {
		Map<String, Object> map = new HashMap<>();
		List<VocabDyadStd> list = new ArrayList<>();

		Map<String, Object> param = new HashMap<>();
		param.put("flag", flagKey);
		param.put("type", type);
		if (arrayKey != null && !arrayKey.isEmpty()) {
			param.put("arrayKey", "%" + arrayKey + "%");
		}
		if (!BaseContants.FLAG_NULL.equals(Integer.parseInt(flagKey))) {
			param.put("start", startStr);
			param.put("checkId", user.getUserId());

			int totalSize = vocabDyadStdDao.retrieveSize(param);

			Map<String, Integer> pageNo = GetListUtil.getPageNoParam(totalSize, startStr);

			int endPage = pageNo.get("endPage");
			int start = pageNo.get("start");
			int startIndex = pageNo.get("startIndex");

			if (startIndex < totalSize) {
				param.put("startIndex", startIndex);
				param.put("orderStr", "gmt_modified desc");
				list = vocabDyadStdDao.retrieveInternList(param);
			}

			Map<String, String> showSearch = new LinkedHashMap<>();
			showSearch.put("arrayKey", "标准词");

			map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, null);
			map.put("showSearch", showSearch);
		} else {
			list = vocabDyadStdDao.retrieveInternList(param);

			map.put("list", list);
		}

		arrangeList(list);

		map.put("isTest", false);

		return new ModelAndView("vocab/dyad_index", map);
	}

	private void arrangeList(List<VocabDyadStd> list) {
		// 将列表中的同义词拆出来放在列表中，维护例句；如果是o+o则需要将是否结合s的数据进行维护
		for (VocabDyadStd dyad : list) {
			List<String> synonymList = new ArrayList<>();
			if (dyad.getSynonym() != null && !dyad.getSynonym().isEmpty()) {
				for (String synonym : dyad.getSynonym().split((char) 1 + "")) {
					synonymList.add(synonym);
				}
			}
			dyad.setSynonymList(synonymList);

			dyad.setShowSentence(dyad.getSentence().split((char) 1 + "")[0]);

			dyad.setSentence(dyad.getSentence().replace((char) 1, '\n'));
		}
	}

	private static Double passPercent = 0.85;

	public ReturnData checkPageTest(String checkedIds, String unCheckedIds, String type, User user) {
		// 将勾选的数据维护成正确的
		if (checkedIds != null && !checkedIds.isEmpty()) {
			vocabDyadStdDao.updateStdFlagByIdsTest(checkedIds, BaseContants.FLAG_RIGHT, user.getUserId());
		}

		// 将未勾选的数据维护成错误的
		if (unCheckedIds != null && !unCheckedIds.isEmpty()) {
			vocabDyadStdDao.updateStdFlagByIdsTest(unCheckedIds, BaseContants.FLAG_WRONG, user.getUserId());
		}

		// 检查是否已经测试完成，如果完成则获取准确率，然后维护是否通过校验字段
		Map<String, Object> param = new HashMap<>();
		param.put("flag", BaseContants.FLAG_NULL);
		param.put("type", type);
		param.put("checkId", user.getUserId());
		List<VocabDyadStd> list = vocabDyadStdDao.retrieveInternTestList(param);

		String msg = "";
		if (list == null || list.isEmpty()) {

			double rightPercent = vocabDyadStdDao.retrieveTestRightPercent(param);
			LOGGER.info("userid=" + user.getUserId() + ";rightPercent" + rightPercent);

			// 备份当前该用户下所有数据
			vocabDyadStdDao.bakData(param);

			if (rightPercent >= passPercent) {

				userAbilityService.pass(user);

				// 删除当前该用户下测试数据
				vocabDyadStdDao.clearData(param);

				msg = "测验通过，开始获取正式数据！";

			} else {

				// 重置当前该用户下测试数据
				vocabDyadStdDao.resetData(param);

				msg = "测验未通过，将重新获取数据进行测验！";
			}
		}

		return ReturnUtil.success(msg);
	}
	
	/**
	 * 将所有正确的二元组对应元素标准词相同的合并起来
	 */
	public void mergeTrueDyadByElementStd() {
		if (!SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_DYAD_MERGE_TRUE_DYAD)) {

			// 刷新为运行中
			SubmitStatus.addSubmitRecords(SubmitStatus.TYPE_DYAD_MERGE_TRUE_DYAD);

			// 初始化二元组的标准分词
			vocabDyadDao.initStdArray();
			
			// 将一些特殊的规则做特殊处理
			vocabDyadDao.initStdArrayByRule();
			
			int count = vocabDyadDao.mergeTrueDyadByElementStd();
			// 一个二元组标准词下对应有多个二元组可以合并，则需要迭代该sql直到没有数据需要修改为止
			while(count > 0) {
				count = vocabDyadDao.mergeTrueDyadByElementStd();
			}
			
			// 删除失效的二元组标准词
			vocabDyadStdDao.deleteNoSynonym();

			// 初始化二元组的标准分词
			vocabDyadDao.initStdArray();
			
			SubmitStatus.removeSubmitRecords(SubmitStatus.TYPE_DYAD_MERGE_TRUE_DYAD);
		}
	}

	/**
	 * 根据o+de 如果所有的de都被o带走，则为正确的o+de，若存在没有带走的de则该二元组错误
	 * @param id
	 * @param user
	 * @return
	 */
	public ReturnData updateODeFlag(String id, User user) {
		VocabDyadStd std = vocabDyadStdDao.retrieveObjectById(Long.parseLong(id));
		// 根据id更改二元组标准词的预判标志
		VocabDyadStd dyad = new VocabDyadStd();
		dyad.setId(Long.parseLong(id));
		dyad.setModifierId(user.getUserId());
		String msg ;
		// 如果存在de没有被o都带走则该二元组错误
		if(std.getCombineS().contains(",0,")){
			dyad.setPreFlag(1);
			msg = "0";
		}else{
			dyad.setPreFlag(0);
			msg = "1";
		}
		vocabDyadStdDao.update(dyad);
		return ReturnUtil.success(msg);
	}
}
